package com.jfl.service.impl.system;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Service;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jfl.base.BaseServiceImpl;
import com.jfl.common.MessageKey;
import com.jfl.common.SqlMapperKey;
import com.jfl.config.Resources;
import com.jfl.exception.BusinessException;
import com.jfl.mapper.SysMenuMapper;
import com.jfl.mapper.SysRoleMenuMapper;
import com.jfl.model.SysMenu;
import com.jfl.model.SysRole;
import com.jfl.system.SysMenuService;

/**
 * 菜单
 * 
 * @author 赵炎
 * @version [V1.00, 2018年12月11日]
 * @since V1.00
 */
@Component
@Service(version = "${jfl.version}")
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenu, SysMenuMapper> implements SysMenuService
{
    
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;
    
    /**
     * 根据用户Id动态获取菜单
     * 
     * @param userId
     * @return
     * @see com.jfl.system.SysMenuService#selectMenusByUserId(java.lang.Long)
     */
    @Override
    public List<SysMenu> selectMenusByUserId(Long userId)
    {
        List<Long> ids = this.mapper.selectMenusByUserId(userId);
        List<SysMenu> menus = queryList(ids);
        // 生成菜单
        return getChildPerms(menus, 0);
    }
    
    /**
     * 根据父节点的Id获取所有子节点
     * 
     * @param menus
     * @param parentId
     * @return
     */
    private List<SysMenu> getChildPerms(List<SysMenu> menus, int parentId)
    {
        List<SysMenu> resultList = Lists.newArrayList();
        menus.forEach(menu -> {
            // 根据传入的某个父节点Id，便利该父节点所有子节点
            if (menu.getParentId() == parentId)
            {
                recursionFn(menus, menu);
                resultList.add(menu);
            }
        });
        return resultList;
    }
    
    /**
     * 递归列表
     * 
     * @param menus
     * @param menu
     */
    private void recursionFn(List<SysMenu> menus, SysMenu menu)
    {
        List<SysMenu> childList = getChildList(menus, menu);
        menu.setChildren(childList);
        menus.forEach(m -> {
            // 判断是否有自己点
            if (hasChild(menus, m))
            {
                childList.forEach(child -> {
                    recursionFn(menus, child);
                });
            }
        });
        
    }
    
    /**
     * 判断是否有子节点
     * 
     * @param menus
     * @param m
     * @return
     * @see [类、类#方法、类#成员]
     */
    private boolean hasChild(List<SysMenu> menus, SysMenu m)
    {
        return getChildList(menus, m).size() > 0 ? true : false;
    }
    
    /**
     * 获取子节点列表
     * 
     * @param menus
     * @param menu
     * @return
     * @see [类、类#方法、类#成员]
     */
    private List<SysMenu> getChildList(List<SysMenu> menus, SysMenu menu)
    {
        List<SysMenu> tlist = Lists.newArrayList();
        menus.forEach(m -> {
            if (m.getParentId().longValue() == menu.getId().longValue())
            {
                tlist.add(m);
            }
        });
        return tlist;
    }
    
    @Override
    public List<Map<String, Object>> roleMenuTreeData(SysRole role)
    {
        Long roleId = role.getId();
        List<Map<String, Object>> trees = Lists.newArrayList();
        Map<String, Object> params = Maps.newHashMap();
        params.put(SqlMapperKey.ENABLE, 1);
        List<SysMenu> menuList = this.mapper.selectByMap(params);
        if (roleId != null)
        {
            List<String> roleMenuList = this.mapper.selectMenuTree(roleId);
            trees = getTrees(menuList, true, roleMenuList, true);
        }
        else
        {
            trees = getTrees(menuList, false, null, true);
        }
        return trees;
    }
    
    /**
     * 对象转菜单树
     * 
     * @param menuList
     *            菜单列表
     * @param isCheck
     *            是否需要选中
     * @param roleMenuList
     *            角色已存在菜单列表
     * @param permsFlag
     *            是否需要显示权限标识
     * @return
     */
    public List<Map<String, Object>> getTrees(List<SysMenu> menuList, boolean isCheck, List<String> roleMenuList, boolean permsFlag)
    {
        List<Map<String, Object>> trees = new ArrayList<Map<String, Object>>();
        for (SysMenu menu : menuList)
        {
            Map<String, Object> deptMap = new HashMap<String, Object>();
            // 转成String 防止Js对Long型数据转换的丢失
            deptMap.put("id", String.valueOf(menu.getId()));
            deptMap.put("pId", String.valueOf(menu.getParentId()));
            deptMap.put("name", transMenuName(menu, roleMenuList, permsFlag));
            deptMap.put("title", menu.getMenuName());
            if (isCheck)
            {
                deptMap.put("checked", roleMenuList.contains(menu.getId() + menu.getPermissions()));
            }
            else
            {
                deptMap.put("checked", false);
            }
            trees.add(deptMap);
        }
        return trees;
    }
    
    public String transMenuName(SysMenu menu, List<String> roleMenuList, boolean permsFlag)
    {
        StringBuffer sb = new StringBuffer();
        sb.append(menu.getMenuName());
        if (permsFlag)
        {
            sb.append("<font color=\"#888\">&nbsp;&nbsp;&nbsp;" + menu.getPermissions() + "</font>");
        }
        return sb.toString();
    }
    
    @Override
    public List<Map<String, Object>> menuTreeData()
    {
        List<Map<String, Object>> trees = new ArrayList<Map<String, Object>>();
        List<SysMenu> menuList = this.mapper.selectByMap(Maps.newHashMap());
        trees = getTrees(menuList, false, null, false);
        return trees;
    }
    
    @Override
    public List<String> getPermissionsByUserId(Long userId)
    {
        return this.mapper.selectPermissionsByUserId(userId);
    }
    @Transactional
    @Override
    public void deleteById(Long menuId) throws BusinessException
    {
        int count = this.mapper.selectCountByParentId(menuId);
        if (count > 0)
        {
            throw new BusinessException(Resources.getMessage(MessageKey.MENU_EXIT_CHILD));
        }
        count = this.sysRoleMenuMapper.countByMenuId(menuId);
        if (count > 0)
        {
            throw new BusinessException(Resources.getMessage(MessageKey.MENU_HAS_ASSIGNED));
        }
        this.mapper.deleteById(menuId);
    }
}
